<template>
  <div class="validate-input-container pb-3">
    <input v-if="tag !== 'textarea'"
           class="form-control"
           :class="{ 'is-invalid': inputRef.error }"
           @blur="ValidateInput"
           v-model="inputRef.val"
           v-bind="$attrs">
    <textarea v-else
              class="form-control"
              :class="{ 'is-invalid': inputRef.error }"
              @blur="ValidateInput"
              v-model="inputRef.val"
              v-bind="$attrs">
    </textarea>
    <span v-if="inputRef.error"
          class="invalid-feedback">{{ inputRef.message }}</span>
  </div>
</template>

<!-- 表单验证组件 -->
<script lang='ts'>
import { defineComponent, reactive, PropType, onMounted, computed } from 'vue'
import { emitter } from './ValidateForm.vue'
// 验证邮箱的正则表达式
const emailReg = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
// const passwordReg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/

// 定义验证范围接口
interface Range {
  length: number
  message: string
}
// 定义验证规则接口
interface RuleProp {
  type: 'requied' | 'email' | 'range' | 'coustom'
  message?: string
  validator?: () => boolean
  min?: Range
  max?: Range
}

export type RulesProp = RuleProp[]

// 兼容单行输入与多行输入的输入框组件
export type TagType = 'input' | 'textarea'

export default defineComponent({
  name: 'ValidateInput',
  props: {
    rules: Array as PropType<RulesProp>,
    modelValue: String,
    tag: {
      type: String as PropType<TagType>,
      //默认渲染input
      default: 'input'
    }
  },
  inheritAttrs: false,
  setup(props, context) {
    //对输入框中的数据进行判断与校验
    const inputRef = reactive({
      val: computed({
        get: () => props.modelValue || '',
        set: val => {
          context.emit('update:modelValue', val)
        }
      }),
      error: false,
      message: ''
    })
    // //自定义组件的双向绑定 手动完成v-model的功能(先改进代码弃用了)
    // const updateValue = (e: Event) => {
    //   const targetValue = (e.target as HTMLInputElement).value
    //   inputRef.val = targetValue
    //   context.emit('update:modelValue', targetValue)
    // }
    //检验各种类型的数据,可拓展
    const ValidateInput = () => {
      if (props.rules) {
        const allPassed = props.rules.every(rule => {
          let passed = true
          // (??)当左侧的操作数为 null 或者 undefined 时，返回其右侧操作数，否则返回左侧操作数
          // inputRef.message = rule.message ?? ''
          inputRef.message = rule.message as string
          switch (rule.type) {
            case 'requied':
              passed = (inputRef.val.trim() !== '')
              break;
            case 'email':
              passed = emailReg.test(inputRef.val)
              break;
            case 'coustom':
              passed = rule.validator ? rule.validator() : true
              break;
            case 'range':
              if (rule.min) {
                if (inputRef.val.trim().length < rule.min.length) {
                  inputRef.message = rule.min.message
                  passed = false
                  break;
                }
              }
              if (rule.max) {
                if (inputRef.val.trim().length > rule.max.length) {
                  inputRef.message = rule.max.message
                  passed = false
                  break;
                }
              }
            default:
              break;
          }
          return passed
        })
        inputRef.error = !allPassed
        return allPassed
      }
      return true
    }
    // 提交后清空
    const clearInput = () => {
      inputRef.val = ''
      inputRef.message = ''
    }
    // 触发组件通信
    onMounted(() => {
      // 发送每一个校验输入框的函数
      emitter.emit('from-item-created', ValidateInput)
      // 发送清空输入框函数
      emitter.emit('from-item-clear', clearInput)
    })
    return {
      inputRef,
      ValidateInput,
      clearInput
    }
  }
})
</script>

<style scoped>
</style>